﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Vux.Helper.Numeric;
using Vux.Helper.File;

namespace Vux.SVCore.Objects
{
    /// <summary>
    /// ===== FAPP: Fami Anti-Phishing Protocol ======
    /// [FAPP(4byte)|Version(1)|Length(4)|Service(1)|SessionId(4)|Data(*)]
    /// </summary>
    public class SVCorePacket
    {
        private byte m_packet_version;
        private int m_packet_length;
        private SVCoreService m_svCore_service;
        private byte[] m_session_id;
        private byte[] m_packet_data;

        public const byte HeaderSize = 14;

        public byte Version
        {
            get { return m_packet_version; }
        }

        public int Length
        {
            get { return m_packet_length; }
        }

        public SVCoreService Service
        {
            get { return m_svCore_service; }
            set { m_svCore_service = value; }
        }

        public int SessionId
        {
            get { return BitConverter.ToInt32(m_session_id, 0); }
            set { m_session_id = BitConverter.GetBytes(value); }
        }

        public byte[] Data
        {
            get { return m_packet_data; }
            set
            {
                SetPayLoad(value);
            }
        }

        public SVCorePacket()
        {
            m_session_id = new byte[] { 0, 0, 0, 0 };
        }

        public void SetPayLoad(byte[] ip_data)
        {
            if (ip_data == null)
            {
                m_packet_length = 0;
                m_packet_data = null;
            }
            else
            {
                m_packet_length = ip_data.Length < 0 ? 0 : ip_data.Length;
                m_packet_data = ip_data;
            }
        }

        public byte[] GetBytes()
        {
            var buffer = new byte[0];
            ByteHelper.Concat(ref buffer, "FAPP");
            ByteHelper.Concat(ref buffer, m_packet_version);
            ByteHelper.Concat(ref buffer, m_packet_length.ToBytes());
            ByteHelper.Concat(ref buffer, (byte)m_svCore_service);
            ByteHelper.Concat(ref buffer, m_session_id);
            ByteHelper.Concat(ref buffer, m_packet_data);
            return buffer;
        }

        public static SVCorePacket GetPacket(byte[] ip_receive_data)
        {
            var v_ap_header = new byte[] { 0x46, 0x41, 0x50, 0x50 };    // FAPP
            var v_ap_actual = new byte[4];
            Array.Copy(ip_receive_data, 0, v_ap_actual, 0, 4);
            for (byte i = 0; i < 4; i++)
            {
                if (v_ap_actual[i] != v_ap_header[i])
                    throw new Exception("Giao thức không hợp lệ");
            }
            var packet = new SVCorePacket();
            packet.m_packet_version = ip_receive_data[4];
            packet.m_packet_length = ByteHelper.ToIntValue(ip_receive_data, 5);
            packet.m_svCore_service = (SVCoreService)ip_receive_data[9];
            packet.m_session_id = ip_receive_data.GetBytes(10, 4);
            packet.m_packet_data = ip_receive_data.GetBytes(HeaderSize);
            return packet;
        }

        public static SVCorePacket GetPacketWithOutData(byte[] ip_receive_data)
        {
            var v_ap_header = new byte[] { 0x46, 0x41, 0x50, 0x50 };    // FAPP
            var v_ap_actual = new byte[4];
            Array.Copy(ip_receive_data, 0, v_ap_actual, 0, 4);
            for (byte i = 0; i < 4; i++)
            {
                if (v_ap_actual[i] != v_ap_header[i])
                    throw new Exception("Giao thức không hợp lệ");
            }
            var packet = new SVCorePacket();
            packet.m_packet_version = ip_receive_data[4];
            packet.m_packet_length = ByteHelper.ToIntValue(ip_receive_data, 5);
            packet.m_svCore_service = (SVCoreService)ip_receive_data[9];
            packet.m_session_id = ip_receive_data.GetBytes(10, 4);
            return packet;
        }

        public static byte[] GetVerifyPacket()
        {
            var packet = new SVCorePacket();
            packet.m_svCore_service = SVCoreService.Verify;
            return packet.GetBytes();
        }

        public static byte[] GetBmpPacket()
        {
            var packet = new SVCorePacket();
            packet.m_svCore_service = SVCoreService.Bmp;
            return packet.GetBytes();
        }

        public static byte[] GetBmpRespPacket(string fileName)
        {
            var packet = new SVCorePacket();
            packet.m_svCore_service = SVCoreService.BmpResp;
            packet.Data = FileReader.ReadAllBytes(fileName);
            return packet.GetBytes();
        }

        public static byte[] GetBmpRespPacket(byte[] data)
        {
            var packet = new SVCorePacket();
            packet.m_svCore_service = SVCoreService.BmpResp;
            packet.Data = data;
            return packet.GetBytes();
        }

        public static byte[] GetAuthPacket(byte[] data)
        {
            var packet = new SVCorePacket();
            packet.m_svCore_service = SVCoreService.Auth;
            packet.Data = data;
            return packet.GetBytes();
        }
    }
}
